# /**
# * Copyright (c) 2022 Beijing Jiaotong University
# * PhotLab is licensed under [Open Source License].
# * You can use this software according to the terms and conditions of the [Open Source License].
# *
# * You may obtain a copy of [Open Source License] at: [https://open.source.license/]
# *
# * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# *
# * See the [Open Source License] for more details.
# */
# /**
# * Author: Shihao Xie
# * Created: Sep. 3, 2022
# * Supported by: National Key Research and Development Program of China
# */

from whoosh.fields import Schema, TEXT, ID, KEYWORD, STORED
from whoosh.index import create_in, open_dir, exists_in
from whoosh.qparser import QueryParser
from whoosh.query import Term
from whoosh.filedb.filestore import FileStorage
from jieba.analyse import ChineseAnalyzer
import os
from phot_server.utils.phot_logger import logger
from phot_server.rpc.graph_data_type.ttypes import PhotComponent
from phot_server.server_config.global_config import BASE_ROOT

class SearchEngine:
    def __init__(self):
        # logger.debug("Search engine is initializing!")
        self.__analyzer = ChineseAnalyzer()
        self.__component_schema = Schema(name=TEXT(stored=True),
                                         category=TEXT(stored=True),
                                         description=TEXT(stored=True, analyzer=self.__analyzer),
                                         path=ID(stored=True, unique=True),
                                         calculationMethod=STORED,
                                         parallelComputingMethod=STORED,
                                         isAnalyzer=STORED)
        self.ix_path = u"{}/phot_server/database/component_document/".format(BASE_ROOT)
        self.ix_index = u"PhotComponentPrototypeIndex"
        if not os.path.exists(self.ix_path):
            os.mkdir(self.ix_path)
        if exists_in(self.ix_path, self.ix_index) is False:
            ix = create_in(self.ix_path, self.__component_schema, indexname=self.ix_index)
            ix.close()

    def add_component_index(self, component: PhotComponent):
        storage = FileStorage(self.ix_path)
        ix = storage.open_index(indexname=self.ix_index)
        writer = ix.writer()
        # with ix.writer() as writer:
        writer.update_document(name=component.name,
                               category=component.category,
                               description=component.description,
                               path=component.path,
                               calculationMethod=component.calculationMethod,
                               parallelComputingMethod=component.parallelComputingMethod,
                               isAnalyzer=component.isAnalyzer)
        # writer.commit()
        writer.commit(optimize=True)
        ix.close()

    def has_index(self, path: str) -> bool:
        storage = FileStorage(self.ix_path)
        ix = storage.open_index(indexname=self.ix_index)
        with ix.searcher() as searcher:
            parser = QueryParser(u"path", ix.schema)
            myquery = parser.parse(path)
            results = searcher.search(myquery)
            if len(results) == 0:
                return False
        return True

    def delete_index(self, path: str) -> bool:
        if self.has_index(path):
            storage = FileStorage(self.ix_path)
            ix = storage.open_index(indexname=self.ix_index)
            writer = ix.writer()
            writer.delete_by_term(u"path", u"".join(path))
            writer.commit(optimize=True)
            ix.close()
            return False
        return True

    def search_index(self, query_string, fields=None) -> list:
        if fields is None:
            fields = [u"name", "description"]
        storage = FileStorage(self.ix_path)
        ix = storage.open_index(indexname=self.ix_index)
        result_dicts = {}
        with ix.searcher() as searcher:
            for field in fields:
                parser = QueryParser(field, ix.schema)
                myquery = parser.parse(query_string)
                results = searcher.search(myquery)
                for result in results:
                    result_dict = result.fields()
                    if result_dicts.get(result_dict["path"], None) is None:
                        result_dicts[result_dict["path"]] = result_dict
        return list(result_dicts.values())
